package com.yoso.controller.jwt;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.SneakyThrows;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.DataInputStream;
import java.io.InputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Map;

/**
 * @author shizejin
 * @date 2022/4/18
 * @description:
 */
@RestController
@RequestMapping("/jwt")
public class JwtController {
    @RequestMapping("/creat")
    public String getToken(){
        String token = JWT.create().withClaim("user","yoso").withAudience("mm").sign(Algorithm.HMAC256("123456"));
        System.out.println("token = " + token);
        String token2 = JWT.create().withExpiresAt(new Date()).sign(Algorithm.HMAC256("1234567"));
        System.out.println("token2 = " + token2);
        Date expiresAt = JWT.decode(token2).getExpiresAt();
        System.out.println(DateUtil.format(expiresAt,"yyyy-MM-dd"));
        return token;
    }
    @RequestMapping("/parse")
    public String parseToken(HttpServletRequest request){
        String token = request.getHeader("token");
        String s = JWT.decode(token).getAudience().get(0);
        return s;
    }


    @SneakyThrows
    @RequestMapping("/parse2")
    public Object parseToken2(HttpServletRequest request){
        String token = request.getHeader("token");

        Jws<Claims> sec = Jwts.parser().setSigningKey(getPublicKey()).parseClaimsJws(token);
        Claims body = sec.getBody();
        Date expiration = body.getExpiration();
        System.out.println(expiration);
        return body;
    }

    @SneakyThrows
    @RequestMapping("/parse3")
    public Object parseToken3(HttpServletRequest request){
        String token = request.getHeader("token");

        Jws<Claims> sec = Jwts.parser().setSigningKey(getPublicKey()).parseClaimsJws(token);
        Claims body = sec.getBody();
        Date expiration = body.getExpiration();
        System.out.println(expiration);
        return body;
    }


    @RequestMapping("/creat2")
    public String getToken2(HttpServletResponse response){
        Map<String, Object> map = CollUtil.newHashMap();
        map.put("id","0425");
        map.put("name","yoso");
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime localDateTime = now.plusMinutes(10);
        Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());


        String token = Jwts.builder().setClaims(map).setExpiration(date).signWith(SignatureAlgorithm.RS256, getPrivateKey()).compact();
        response.setHeader("token",token);
        return token;
    }

    @SneakyThrows
    @RequestMapping("/creat3")
    public String getToken3(HttpServletResponse response){
        Map<String, Object> map = CollUtil.newHashMap();
        map.put("id","0425");
        map.put("name","yoso");
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime localDateTime = now.plusMinutes(10);
        Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());


        String token = Jwts.builder().setClaims(map).setExpiration(date).signWith(SignatureAlgorithm.RS256, getPublicKey()).compact();
        response.setHeader("token",token);
        return token;
    }

    public PrivateKey getPrivateKey() {
        try{
            String filename = "jwt/jwt_pri.key";
            InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(filename);
            DataInputStream dis = new DataInputStream(resourceAsStream);
            byte[] keyBytes = new byte[resourceAsStream.available()];
            dis.readFully(keyBytes);
            dis.close();
            PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(spec);
        }catch (Exception e){
            return null;
        }
    }

    public PublicKey getPublicKey() throws Exception {
        try{
            String filename = "jwt/jwt_pub.key";
            InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(filename);
            DataInputStream dis = new DataInputStream(resourceAsStream);
            byte[] keyBytes = new byte[resourceAsStream.available()];
            dis.readFully(keyBytes);
            dis.close();
            X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePublic(spec);
        }catch (Exception e){
            throw  new Exception(e.getMessage(),e);
        }
    }

}
